import os
import json
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from PIL import Image, ImageTk

class AdvancedImageViewer:
    def __init__(self, root):
        self.root = root
        self.root.title("高级JPG图片查看器")
        
        # 初始化变量
        self.image_dir = ""
        self.image_files = []
        self.current_index = 0
        self.zoom_level = 1.0  # 初始缩放级别
        
        # 初始化UI
        self.setup_ui()
    
    def setup_ui(self):
        # 创建主框架
        self.main_frame = ttk.Frame(self.root, padding="10")
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 目录选择区域
        dir_frame = ttk.Frame(self.main_frame)
        dir_frame.pack(pady=5, fill=tk.X)
        
        ttk.Label(dir_frame, text="图片目录:").pack(side=tk.LEFT)
        
        self.dir_entry = ttk.Entry(dir_frame, width=50)
        self.dir_entry.pack(side=tk.LEFT, padx=5)
        
        dir_button = ttk.Button(
            dir_frame, 
            text="浏览...", 
            command=self.browse_directory
        )
        dir_button.pack(side=tk.LEFT)
        
        load_button = ttk.Button(
            dir_frame, 
            text="加载图片", 
            command=self.load_images
        )
        load_button.pack(side=tk.LEFT, padx=5)
        
        # 添加保存和加载按钮
        save_button = ttk.Button(
            dir_frame, 
            text="保存列表", 
            command=self.save_image_list
        )
        save_button.pack(side=tk.LEFT, padx=5)
        
        load_list_button = ttk.Button(
            dir_frame, 
            text="加载列表", 
            command=self.load_image_list
        )
        load_list_button.pack(side=tk.LEFT, padx=5)
        
        # 创建图片显示区域
        self.image_frame = ttk.Frame(self.main_frame)
        self.image_frame.pack(pady=10, fill=tk.BOTH, expand=True)
        
        # 创建画布和滚动条
        self.canvas = tk.Canvas(self.image_frame, bg="gray")
        self.v_scroll = ttk.Scrollbar(
            self.image_frame, 
            orient=tk.VERTICAL, 
            command=self.canvas.yview
        )
        self.h_scroll = ttk.Scrollbar(
            self.image_frame, 
            orient=tk.HORIZONTAL, 
            command=self.canvas.xview
        )
        self.h_scroll.pack(side=tk.BOTTOM, fill=tk.X)
        
        # 配置画布的滚动条
        self.canvas.configure(yscrollcommand=self.v_scroll.set, xscrollcommand=self.h_scroll.set)
        
        # 布局：画布在左侧，垂直滚动条在右侧，水平滚动条在底部
        self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.v_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        self.h_scroll.pack(side=tk.BOTTOM, fill=tk.X)
        
        # 图片容器（用于滚动）
        self.image_container = tk.Frame(self.canvas)
        self.canvas.create_window((0, 0), window=self.image_container, anchor=tk.NW)
        
        # 绑定鼠标滚轮缩放
        self.canvas.bind("<MouseWheel>", self.on_mousewheel)
        
        # 创建下拉选择框
        self.file_var = tk.StringVar()
        self.file_combobox = ttk.Combobox(
            self.main_frame, 
            textvariable=self.file_var,
            state="readonly"
        )
        self.file_combobox.pack(pady=5, fill=tk.X)
        self.file_combobox.bind("<<ComboboxSelected>>", self.on_combobox_selected)
        
        # 创建控制按钮框架
        self.button_frame = ttk.Frame(self.main_frame)
        self.button_frame.pack(pady=10)
        
        # 翻页按钮
        self.prev_button = ttk.Button(
            self.button_frame, 
            text="上一张", 
            command=self.show_previous_image
        )
        self.prev_button.pack(side=tk.LEFT, padx=5)
        
        self.next_button = ttk.Button(
            self.button_frame, 
            text="下一张", 
            command=self.show_next_image
        )
        self.next_button.pack(side=tk.LEFT, padx=5)
        
        # 缩放按钮
        self.zoom_in_button = ttk.Button(
            self.button_frame, 
            text="放大 (+)", 
            command=self.zoom_in
        )
        self.zoom_in_button.pack(side=tk.LEFT, padx=5)
        
        self.zoom_out_button = ttk.Button(
            self.button_frame, 
            text="缩小 (-)", 
            command=self.zoom_out
        )
        self.zoom_out_button.pack(side=tk.LEFT, padx=5)
        
        self.reset_zoom_button = ttk.Button(
            self.button_frame, 
            text="重置缩放", 
            command=self.reset_zoom
        )
        self.reset_zoom_button.pack(side=tk.LEFT, padx=5)
        
        # 状态标签
        self.status_var = tk.StringVar()
        self.status_var.set("请选择图片目录")
        self.status_label = ttk.Label(
            self.main_frame, 
            textvariable=self.status_var
        )
        self.status_label.pack(pady=5)
        
        # 绑定窗口大小变化事件
        self.root.bind("<Configure>", self.on_window_resize)
    
    def load_image_list(self):
        """从JSON文件加载图片列表"""
        file_path = filedialog.askopenfilename(
            filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")],
            title="加载图片列表"
        )
        
        if not file_path:  # 用户取消了选择
            return
            
        try:
            # 读取JSON文件
            with open(file_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
                
            # 更新图片目录和文件列表
            self.image_dir = data.get("image_directory", "")
            self.image_files = data.get("image_files", [])
            self.current_index = data.get("current_index", 0)
            
            # 更新目录显示
            self.dir_entry.delete(0, tk.END)
            self.dir_entry.insert(0, self.image_dir)
            
            # 更新下拉列表
            self.update_file_combobox()
            
            self.status_var.set(f"已从 {file_path} 加载 {len(self.image_files)} 张图片")
            messagebox.showinfo("成功", "图片列表已成功加载")
            
            # 如果有图片，显示第一张
            if self.image_files:
                #self.current_index = 0
                self.show_image(self.image_files[self.current_index])
                
        except Exception as e:
            messagebox.showerror("错误", f"加载文件时出错: {str(e)}")
            self.status_var.set(f"加载失败: {str(e)}")
    
    def update_file_combobox(self):
        """更新文件选择下拉框"""
        self.file_combobox['values'] = self.image_files
        if self.image_files:
            self.file_var.set(self.image_files[0])
        else:
            self.file_var.set('')
    
    def save_image_list(self):
        """将图片列表保存为JSON文件"""
        if not self.image_files:
            messagebox.showwarning("警告", "没有可保存的图片列表")
            return
            
        # 获取保存路径
        file_path = filedialog.asksaveasfilename(
            defaultextension=".json",
            filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")],
            title="保存图片列表"
        )
        
        if not file_path:  # 用户取消了保存
            return
            
        try:
            # 准备要保存的数据
            data = {
                "image_directory": self.image_dir,
                "image_files": self.image_files,
                "current_index": self.current_index
            }
            
            # 写入JSON文件
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, indent=4, ensure_ascii=False)
                
            self.status_var.set(f"图片列表已保存到: {file_path}")
            messagebox.showinfo("成功", "图片列表已成功保存")
            
        except Exception as e:
            messagebox.showerror("错误", f"保存文件时出错: {str(e)}")
            self.status_var.set(f"保存失败: {str(e)}")
    
    # 其他方法保持不变...
    # browse_directory, load_images, show_image, apply_zoom, zoom_in, zoom_out, reset_zoom,
    # on_mousewheel, show_next_image, show_previous_image, on_combobox_selected, on_window_resize
    # 这些方法保持不变，与之前相同
    
    def browse_directory(self):
        """打开目录选择对话框"""
        directory = filedialog.askdirectory()
        if directory:
            self.dir_entry.delete(0, tk.END)
            self.dir_entry.insert(0, directory)
    
    def load_images(self):
        """加载指定目录中的JPG图片文件"""
        self.image_dir = self.dir_entry.get()
        if not self.image_dir:
            messagebox.showwarning("警告", "请先选择图片目录")
            return
            
        if not os.path.isdir(self.image_dir):
            messagebox.showerror("错误", f"目录 '{self.image_dir}' 不存在")
            return
        
        image_files = [
            f for f in os.listdir(self.image_dir) 
            if f.lower().endswith(('.jpg', '.jpeg'))
        ]
        
        if not image_files:
            messagebox.showinfo("信息", f"目录 '{self.image_dir}' 中没有找到JPG图片")
            return
        self.image_files = sorted(image_files)
        # 更新下拉框
        self.file_combobox['values'] = self.image_files
        self.file_var.set(self.image_files[0])
        self.status_var.set(f"找到 {len(self.image_files)} 张JPG图片")
        
        # 显示第一张图片
        self.current_index = 0
        self.zoom_level = 1.0
        self.show_image(self.image_files[self.current_index])
    
    def show_image(self, image_file):
        """显示指定图片"""
        try:
            image_path = os.path.join(self.image_dir, image_file)
            
            # 打开图片
            self.original_img = Image.open(image_path)
            self.apply_zoom()
            
            # 更新状态
            self.current_index = self.image_files.index(image_file)
            self.status_var.set(
                f"图片 {self.current_index + 1}/{len(self.image_files)}: {image_file} "
                f"(缩放: {int(self.zoom_level * 100)}%)"
            )
            
        except Exception as e:
            self.status_var.set(f"无法加载图片 {image_file}: {str(e)}")
            messagebox.showerror("错误", f"无法加载图片 {image_file}: {str(e)}")
    
    def apply_zoom(self):
        """应用当前缩放级别"""
        if not hasattr(self, 'original_img'):
            return
        
        # 计算缩放后的尺寸
        original_width, original_height = self.original_img.size
        new_width = int(original_width * self.zoom_level)
        new_height = int(original_height * self.zoom_level)
    
        # 选择重采样方法
        resample_method = Image.Resampling.LANCZOS if self.zoom_level > 1.0 else Image.Resampling.BILINEAR
    
        # 缩放图片
        img = self.original_img.resize(
            (new_width, new_height), 
            resample_method
        )
    
        # 转换为Tkinter可显示的格式
        self.tk_img = ImageTk.PhotoImage(img)
    
        # 清除之前的图片
        for widget in self.image_container.winfo_children():
            widget.destroy()
        
        # 显示新图片
        self.image_label = ttk.Label(self.image_container, image=self.tk_img)
        self.image_label.pack()
    
        # 更新画布滚动区域
        self.canvas.config(scrollregion=self.canvas.bbox("all"))
    
    def zoom_in(self):
        """放大图片"""
        self.zoom_level *= 1.2
        if self.zoom_level > 5.0:
            self.zoom_level = 5.0
        self.apply_zoom()
    
    def zoom_out(self):
        """缩小图片"""
        self.zoom_level /= 1.2
        if self.zoom_level < 0.1:
            self.zoom_level = 0.1
        self.apply_zoom()
    
    def reset_zoom(self):
        """重置缩放级别"""
        self.zoom_level = 1.0
        self.apply_zoom()
    
    def on_mousewheel(self, event):
        """鼠标滚轮缩放"""
        if event.delta > 0:  # 向上滚动，放大
            self.zoom_in()
        else:  # 向下滚动，缩小
            self.zoom_out()
    
    def show_next_image(self):
        """显示下一张图片"""
        if not self.image_files:
            return
            
        self.current_index = (self.current_index + 1) % len(self.image_files)
        self.show_image(self.image_files[self.current_index])
    
    def show_previous_image(self):
        """显示上一张图片"""
        if not self.image_files:
            return
            
        self.current_index = (self.current_index - 1) % len(self.image_files)
        self.show_image(self.image_files[self.current_index])
    
    def on_combobox_selected(self, event):
        """当下拉框选择改变时调用"""
        selected_file = self.file_var.get()
        if selected_file in self.image_files:
            self.show_image(selected_file)
    
    def on_window_resize(self, event):
        """窗口大小改变时调整滚动区域"""
        if hasattr(self, 'tk_img'):
            self.canvas.config(scrollregion=self.canvas.bbox("all"))

if __name__ == "__main__":
    root = tk.Tk()
    root.geometry("800x600")
    
    # 允许窗口调整大小
    root.resizable(True, True)
    
    app = AdvancedImageViewer(root)
    root.mainloop()